package com.example.teemor.es_demo.repository.clickhouse;

import com.example.teemor.es_demo.config.LogManagementProperties;
import com.example.teemor.es_demo.entity.ServiceLog;
import com.example.teemor.es_demo.entity.UserBehavior;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.List;

/**
 * ClickHouse日志数据访问层
 * 负责将日志数据写入ClickHouse数据库
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class LogRepository {
    
    @Qualifier("clickHouseJdbcTemplate")
    private final JdbcTemplate clickHouseJdbcTemplate;
    private final LogManagementProperties properties;
    
    /**
     * 批量插入服务日志
     */
    public void batchInsertServiceLogs(List<ServiceLog> logs) {
        if (logs == null || logs.isEmpty()) {
            return;
        }
        
        String tableName = properties.getClickhouse().getTables().getServiceLog();
        String sql = String.format(
            "INSERT INTO %s (timestamp, service_name, level, thread_id, class_name, method_name, content, trace_id, source_ip, exception_class, exception_message, stack_trace) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            tableName
        );
        
        try {
            clickHouseJdbcTemplate.batchUpdate(sql, logs, logs.size(), (ps, log) -> {
                // ClickHouse DateTime不支持毫秒，需要截断到秒
                LocalDateTime truncatedTime = log.getTimestamp().truncatedTo(java.time.temporal.ChronoUnit.SECONDS);
                ps.setTimestamp(1, Timestamp.from(truncatedTime.atZone(ZoneId.systemDefault()).toInstant()));
                ps.setString(2, log.getServiceName());
                ps.setString(3, log.getLevel());
                ps.setString(4, log.getThreadId());
                ps.setString(5, log.getClassName());
                ps.setString(6, log.getMethodName());
                ps.setString(7, log.getContent());
                ps.setString(8, log.getTraceId());
                ps.setString(9, log.getSourceIp());
                ps.setString(10, log.getExceptionClass());
                ps.setString(11, log.getExceptionMessage());
                ps.setString(12, log.getStackTrace());
            });
            
            log.info("成功批量插入服务日志 {} 条", logs.size());
            
        } catch (Exception e) {
            log.error("批量插入服务日志失败，数量: {}", logs.size(), e);
            throw new RuntimeException("批量插入服务日志失败", e);
        }
    }
    
    /**
     * 批量插入用户行为日志
     */
    public void batchInsertUserBehaviors(List<UserBehavior> behaviors) {
        if (behaviors == null || behaviors.isEmpty()) {
            return;
        }
        
        String tableName = properties.getClickhouse().getTables().getUserBehavior();
        String sql = String.format(
            "INSERT INTO %s (timestamp, user_id, session_id, event_type, page_url, page_title, user_agent, device_info, browser_info, os_info, screen_resolution, event_data, referrer, ip_address, location) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            tableName
        );
        
        try {
            clickHouseJdbcTemplate.batchUpdate(sql, behaviors, behaviors.size(), (ps, behavior) -> {
                // ClickHouse DateTime不支持毫秒，需要截断到秒
                LocalDateTime truncatedTime = behavior.getTimestamp().truncatedTo(java.time.temporal.ChronoUnit.SECONDS);
                ps.setTimestamp(1, Timestamp.from(truncatedTime.atZone(ZoneId.systemDefault()).toInstant()));
                ps.setString(2, behavior.getUserId());
                ps.setString(3, behavior.getSessionId());
                ps.setString(4, behavior.getEventType());
                ps.setString(5, behavior.getPageUrl());
                ps.setString(6, behavior.getPageTitle());
                ps.setString(7, behavior.getUserAgent());
                ps.setString(8, behavior.getDeviceInfo());
                ps.setString(9, behavior.getBrowserInfo());
                ps.setString(10, behavior.getOsInfo());
                ps.setString(11, behavior.getScreenResolution());
                ps.setString(12, behavior.getEventData());
                ps.setString(13, behavior.getReferrer());
                ps.setString(14, behavior.getIpAddress());
                ps.setString(15, behavior.getLocation());
            });
            
            log.info("成功批量插入用户行为日志 {} 条", behaviors.size());
            
        } catch (Exception e) {
            log.error("批量插入用户行为日志失败，数量: {}", behaviors.size(), e);
            throw new RuntimeException("批量插入用户行为日志失败", e);
        }
    }
    
    /**
     * 查询服务日志
     */
    public List<ServiceLog> queryServiceLogs(String startTime, String endTime, String keyword, String level, int page, int size) {
        String tableName = properties.getClickhouse().getTables().getServiceLog();
        StringBuilder sql = new StringBuilder("SELECT * FROM ").append(tableName).append(" WHERE 1=1");
        
        if (startTime != null && !startTime.isEmpty()) {
            sql.append(" AND timestamp >= '").append(startTime).append("'");
        }
        if (endTime != null && !endTime.isEmpty()) {
            sql.append(" AND timestamp <= '").append(endTime).append("'");
        }
        if (keyword != null && !keyword.isEmpty()) {
            sql.append(" AND (content LIKE '%").append(keyword).append("%' OR class_name LIKE '%").append(keyword).append("%')");
        }
        if (level != null && !level.isEmpty()) {
            sql.append(" AND level = '").append(level).append("'");
        }
        
        sql.append(" ORDER BY timestamp DESC LIMIT ").append(size).append(" OFFSET ").append(page * size);
        
        return clickHouseJdbcTemplate.query(sql.toString(), (rs, rowNum) -> 
            ServiceLog.builder()
                .timestamp(rs.getTimestamp("timestamp").toLocalDateTime())
                .serviceName(rs.getString("service_name"))
                .level(rs.getString("level"))
                .threadId(rs.getString("thread_id"))
                .className(rs.getString("class_name"))
                .methodName(rs.getString("method_name"))
                .content(rs.getString("content"))
                .traceId(rs.getString("trace_id"))
                .sourceIp(rs.getString("source_ip"))
                .exceptionClass(rs.getString("exception_class"))
                .exceptionMessage(rs.getString("exception_message"))
                .stackTrace(rs.getString("stack_trace"))
                .build()
        );
    }
    
    /**
     * 查询用户行为日志
     */
    public List<UserBehavior> queryUserBehaviors(String startTime, String endTime, String keyword, int page, int size) {
        String tableName = properties.getClickhouse().getTables().getUserBehavior();
        StringBuilder sql = new StringBuilder("SELECT * FROM ").append(tableName).append(" WHERE 1=1");
        
        if (startTime != null && !startTime.isEmpty()) {
            sql.append(" AND timestamp >= '").append(startTime).append("'");
        }
        if (endTime != null && !endTime.isEmpty()) {
            sql.append(" AND timestamp <= '").append(endTime).append("'");
        }
        if (keyword != null && !keyword.isEmpty()) {
            sql.append(" AND (page_url LIKE '%").append(keyword).append("%' OR event_type LIKE '%").append(keyword).append("%')");
        }
        
        sql.append(" ORDER BY timestamp DESC LIMIT ").append(size).append(" OFFSET ").append(page * size);
        
        return clickHouseJdbcTemplate.query(sql.toString(), (rs, rowNum) -> 
            UserBehavior.builder()
                .timestamp(rs.getTimestamp("timestamp").toLocalDateTime())
                .userId(rs.getString("user_id"))
                .sessionId(rs.getString("session_id"))
                .eventType(rs.getString("event_type"))
                .pageUrl(rs.getString("page_url"))
                .pageTitle(rs.getString("page_title"))
                .userAgent(rs.getString("user_agent"))
                .deviceInfo(rs.getString("device_info"))
                .browserInfo(rs.getString("browser_info"))
                .osInfo(rs.getString("os_info"))
                .screenResolution(rs.getString("screen_resolution"))
                .eventData(rs.getString("event_data"))
                .referrer(rs.getString("referrer"))
                .ipAddress(rs.getString("ip_address"))
                .location(rs.getString("location"))
                .build()
        );
    }
    
    /**
     * 统计服务日志数量
     */
    public long countServiceLogs(String startTime, String endTime, String keyword, String level) {
        String tableName = properties.getClickhouse().getTables().getServiceLog();
        StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM ").append(tableName).append(" WHERE 1=1");
        
        if (startTime != null && !startTime.isEmpty()) {
            sql.append(" AND timestamp >= '").append(startTime).append("'");
        }
        if (endTime != null && !endTime.isEmpty()) {
            sql.append(" AND timestamp <= '").append(endTime).append("'");
        }
        if (keyword != null && !keyword.isEmpty()) {
            sql.append(" AND (content LIKE '%").append(keyword).append("%' OR class_name LIKE '%").append(keyword).append("%')");
        }
        if (level != null && !level.isEmpty()) {
            sql.append(" AND level = '").append(level).append("'");
        }
        
        return clickHouseJdbcTemplate.queryForObject(sql.toString(), Long.class);
    }
    
    /**
     * 统计用户行为日志数量
     */
    public long countUserBehaviors(String startTime, String endTime, String keyword) {
        String tableName = properties.getClickhouse().getTables().getUserBehavior();
        StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM ").append(tableName).append(" WHERE 1=1");
        
        if (startTime != null && !startTime.isEmpty()) {
            sql.append(" AND timestamp >= '").append(startTime).append("'");
        }
        if (endTime != null && !endTime.isEmpty()) {
            sql.append(" AND timestamp <= '").append(endTime).append("'");
        }
        if (keyword != null && !keyword.isEmpty()) {
            sql.append(" AND (page_url LIKE '%").append(keyword).append("%' OR event_type LIKE '%").append(keyword).append("%')");
        }
        
        return clickHouseJdbcTemplate.queryForObject(sql.toString(), Long.class);
    }
}